package com.tian.arch.function.http

import com.tian.arch.Foundation
import com.tian.arch.GlobalConfig
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import retrofit2.Retrofit


/**
 * 管理retrofit对象
 */
object RetrofitManager {

    private var retrofit: Retrofit? = null
    private val retrofitServiceCache = mutableMapOf<String, Any>()
    private lateinit var okhttpClient: OkHttpClient

    private fun <T> createApiService(cls: Class<T>): T {
        if (retrofit == null) {
            initDefaultRetrofit()
        }
        return retrofit!!.create(cls)
    }

    private fun initDefaultRetrofit() {
        val config = Foundation.globalConfig()

        requireNotNull(config) {
            throw java.lang.RuntimeException("u must set a default NetworkPolicy at first")
        }
        okhttpClient = createOkHttpClientFromConfig(config)
        val httpUrl = config.networkPolicyProvider?.createNetworkPolicy()?.getPolicyDomain()?.toHttpUrlOrNull()

        httpUrl?.let {
            buildRetrofit(config, httpUrl, okhttpClient)
        }
    }

    private fun createOkHttpClientFromConfig(config: GlobalConfig): OkHttpClient {
        return OkHttpClient
            .Builder()
            .run {
                config.okhttpConfig?.invoke(this) ?: this
            }.build()
    }

    private fun buildRetrofit(config: GlobalConfig, domainUrl: HttpUrl, client: OkHttpClient) {
        retrofit = Retrofit
            .Builder()
            .baseUrl(domainUrl)
            .client(client)
            .run {
                config.retrofitConfig?.invoke(this) ?: this
            }
            .build()
    }

    /**
     * 切换base url
     */
    fun changeServer(baseUrl: HttpUrl) {
        val config = Foundation.globalConfig()
        buildRetrofit(config, baseUrl, createOkHttpClientFromConfig(config))
        synchronized(retrofitServiceCache) {
            retrofitServiceCache.clear()
        }
    }

    /**
     * 获取Api的实现
     */
    fun <T> obtainApiService(service: Class<T>): T {
        var apiService: T?
        synchronized(retrofitServiceCache) {
            apiService = retrofitServiceCache[service.name] as T
            if (apiService == null) {
                apiService = createApiService(service)
                retrofitServiceCache[service.name] = apiService as Any
            }
        }
        return apiService!!
    }

}